package labb1.fordjupn;

import labb1.del2.NoSuchCardException;

import java.util.Arrays;
import java.util.Scanner;

/**
 * @author Mikko Puustinen (mikko.puustinen@gmail.com)
 * @version 0.1, 2007-nov-01
 */
public class GameUI {
    private static Scanner scanner = new Scanner(System.in);
    private PlayerFactory playerFactory;

    /**
     * Creates a text UI.
     *
     * @param playerFactory PlayerFactory to use.
     */
    public GameUI(PlayerFactory playerFactory) {
        this.playerFactory = playerFactory;
        //TODO: remove the following test lines
        playerFactory.addComputer();
        playerFactory.addComputer();
        //playerFactory.addPlayer("Mikko");
        mainMenu();
    }

    /**
     * Starts the playerFactory.
     */
    private void startGame() {
        InSeaGame game = new InSeaGame(playerFactory);
        int numOfPlayers = playerFactory.numberOfPlayers();
        int currentPlayer;
        int pToTakeFrom = 0;
        int chosenCard = 0;
        String name;
        String opponent;
        boolean isValidInput;
        boolean slowMode = true;

        while (game.isRunning()) {
            isValidInput = false;
            currentPlayer = game.getIndexOfCurrentPlayer();
            name = playerFactory.getPlayerNameAt(currentPlayer);

            if (game.isActivePlayerComputer()) {
                pToTakeFrom = game.randomOpponent();
                chosenCard = game.randomValue();
            } else {
                if (numOfPlayers <= 2) {
                    if (currentPlayer == 0)
                        pToTakeFrom = 1;
                    else
                        pToTakeFrom = 0;
                } else {
                    showAllPlayer(name);
                    while (!isValidInput) {
                        System.out.print("\nWhich player to ask for cards?: ");
                        try {
                            pToTakeFrom = Integer.parseInt(scanner.nextLine());
                        } catch (Exception e) {
                            pToTakeFrom = -1;
                        }

                        if (pToTakeFrom == currentPlayer || pToTakeFrom < 0 || pToTakeFrom > numOfPlayers - 1) {
                            System.err.println("Error in input. Choose again.");
                        } else {
                            isValidInput = true;
                        }
                    }
                    isValidInput = false;
                }

                showCards(currentPlayer);
                //System.out.println("----------");
                while (!isValidInput) {
                    //showCards(0);
                    System.out.print("\nWhich value to ask for?: ");
                    try {
                        chosenCard = Integer.parseInt(scanner.nextLine());
                    } catch (Exception e) {
                        chosenCard = -1;
                    }

                    try {
                        chosenCard = playerFactory.getCardValueAt(currentPlayer, chosenCard);
                        isValidInput = true;
                    } catch (NoSuchCardException e) {
                        System.err.println("Input error, choose again.");
                        isValidInput = false;
                    }
                }
            }

            opponent = playerFactory.getPlayerNameAt(pToTakeFrom);
            if (game.hasOpponentValue(pToTakeFrom, chosenCard)) {
                System.out.println("\n\t" + name + " took all cards with the value " + chosenCard + " from " + opponent + "\n");
                if (game.hasFourOfAKind()) {
                    System.out.println(name + " had a four of a kind!");
                }
            } else {
                System.out.println("\n\tGO FISH, " + name + "! " + opponent + " has no " + chosenCard + "!\n");
                game.takeCardFromDeck(currentPlayer);
                if (game.hasFourOfAKind()) {
                    System.out.println(name + " had a four of a kind!");
                }
                if (slowMode)
                    waitForEnter();
                clearScreen();

                game.nextPlayer();
            }
        }
    }

    /**
     * Shows the main menu.
     */
    private void mainMenu() {
        int choice;

        clearScreen();
        System.out.print("1. Add player\n2. Remove player\n3. Play!\n4. Highscore\n5. Quit\n> ");
        try {
            String s = scanner.nextLine();
            choice = Integer.valueOf(s);
        } catch (Exception e) {
            choice = 0;
        }
        switch (choice) {
            case 1:
                addPlayer();
                break;
            case 2:
                removePlayer();
                break;
            case 3:
                for (int i = 0; i < 1; i++) {
                    startGame();
                }
                break;
            case 4:
                highscore();
                break;
            case 5:
                System.exit(0);
                break;
            default:
        }

        mainMenu();
    }

    /**
     * Shows a simple menu where the user can add human and computer Players.
     */
    private void addPlayer() {
        int choice;

        System.out.print("\n\n1. Add human player\n2. Add computer player\n3. Return to menu\n> ");
        try {
            String c = scanner.nextLine();
            choice = Integer.valueOf(c);
        } catch (Exception e) {
            choice = 0;
        }

        switch (choice) {
            case 1:
                String name;

                System.out.print("Player name: ");
                try {
                    name = scanner.nextLine();
                } catch (Exception e) {
                    System.out.println("Error while reading, no player added");
                    return;
                }
                if (!playerFactory.addPlayer(name)) {
                    System.out.println("Player with that name already exists.");
                    addPlayer();
                }
                break;
            case 2:
                playerFactory.addComputer();
                break;
            case 3:
            default:
                break;
        }
    }

    /**
     * Removes the chosen Player.
     */
    private void removePlayer() {
        int choice;
        int numOfPlayers = playerFactory.numberOfPlayers();

        if (numOfPlayers > 0) {
            showAllPlayer("");

            System.out.print("Enter the number of the player to remove: ");
            try {
                String s = scanner.nextLine();
                choice = Integer.valueOf(s);
            } catch (Exception e) {
                choice = -1;
            }

            if (choice < 0 || choice >= numOfPlayers) {
                System.out.println("This player does not exist.");
            } else {
                playerFactory.removePlayer(playerFactory.getPlayerNameAt(choice));
            }
        }
    }

    /**
     *
     */
    private void highscore() {
        int[] wins = playerFactory.getAllPlayerWins();
        Arrays.sort(wins);
        if (wins.length > 0) {
            String[] players = playerFactory.getAllPlayerNames();
            for (int i = players.length - 1; i >= 0; i--) {
                System.out.println(players[i] + ": " + wins[i] + " wins");
            }

            waitForEnter();
        }
    }

    /**
     * Shows all the Players. If the parameter name is used this name will NOT
     * be included in the showed cards if the name exists.
     *
     * @param name the name of the Player NOT to include in the list.
     */
    private void showAllPlayer(String name) {
        String[] names = playerFactory.getAllPlayerNames();
        for (int i = 0; i < names.length; i++) {
            if (names[i].equals(name)) {
            } else {
                System.out.println(i + "." + names[i]);
            }
        }

    }

    /**
     * Shows all the card that the Player has.
     *
     * @param actualPlayer the actual player.
     *
     * @return the number of Cards.
     */
    private int showCards(int actualPlayer) {
        int i = 0;
        for (String str : playerFactory.getPlayerCards(actualPlayer)) {
            System.out.println(i + ". " + str);
            i++;
        }

        return i + 1;
    }

    /**
     * "Clears" the console.
     */
    private void clearScreen() {
        for (int i = 0; i < 15; i++)
            System.out.print("\n");
    }

    /**
     * Waits for the user to press ENTER.
     */
    private void waitForEnter() {
        System.out.print("\nPress ENTER to continue.");
        try {
            scanner.nextLine();
        } catch (Exception e) {
            //
        }
    }
}
